type TimeFunction<T extends (...args: any[]) => any> = (
  func: T,
  delay: number
) => T;

/**
 * 防抖函数
 * @param func 执行函数
 * @param delay 防抖时间
 * @returns T
 */
export const debounce: TimeFunction<any> = <T extends (...args: any[]) => any>(
  func: T,
  delay: number
) => {
  let timerId: ReturnType<typeof setTimeout>;

  return function (this: any, ...args: Parameters<T>) {
    clearTimeout(timerId);

    timerId = setTimeout(() => {
      func.apply(this, args);
    }, delay) as any;
  } as T;
};

/**
 * 节流函数
 * @param func 执行函数
 * @param delay 节流时间
 * @returns T
 */
export const throttle: TimeFunction<any> = <T extends (...args: any[]) => any>(
  func: T,
  delay: number
) => {
  let timerId: ReturnType<typeof setTimeout>;
  let lastExecTime = 0;

  return function (this: any, ...args: Parameters<T>) {
    const currentTime = Date.now();
    const elapsed = currentTime - lastExecTime;

    if (elapsed >= delay) {
      lastExecTime = currentTime;
      func.apply(this, args);
    } else {
      clearTimeout(timerId);

      timerId = setTimeout(() => {
        lastExecTime = Date.now();
        func.apply(this, args);
      }, delay - elapsed) as any;
    }
  } as T;
};
